using System;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Web;
using System.Web.Hosting;
using System.Web.SessionState;

namespace Framework.Library.Core.Utils.Web
{
    public sealed class MockHttpContext
    {
        // NOTE: This code is based on the following article:
        // http://righteousindignation.gotdns.org/blog/archive/2004/04/13/149.aspx
        private const string ContextKeyAspSession = "AspSession";
        private const string ThreadDataKeyAppPath = ".appPath";
        private const string ThreadDataKeyAppPathValue = "c:\\inetpub\\wwwroot\\webapp\\";
        private const string ThreadDataKeyAppVPath = ".appVPath";
        private const string ThreadDataKeyAppVPathValue = "/webapp";
        private const string WorkerRequestPage = "default.aspx";

        private readonly HttpContext _context;

        private MockHttpContext()
        {
        }

        public MockHttpContext(bool isSecure)
            : this()
        {
            Thread.GetDomain().SetData(ThreadDataKeyAppPath, ThreadDataKeyAppPathValue);
            Thread.GetDomain().SetData(ThreadDataKeyAppVPath, ThreadDataKeyAppVPathValue);
            SimpleWorkerRequest request = new WorkerRequest(WorkerRequestPage, string.Empty, new StringWriter(),
                                                            isSecure);
            _context = new HttpContext(request);

            var container = new HttpSessionStateContainer(
                Guid.NewGuid().ToString("N"), new SessionStateItemCollection(), new HttpStaticObjectsCollection(),
                5, true, HttpCookieMode.AutoDetect, SessionStateMode.InProc, false);

            var state = Activator.CreateInstance(
                typeof (HttpSessionState),
                BindingFlags.Public | BindingFlags.NonPublic |
                BindingFlags.Instance | BindingFlags.CreateInstance,
                null,
                new object[] {container}, CultureInfo.CurrentCulture) as HttpSessionState;
            _context.Items[ContextKeyAspSession] = state;
        }

        public HttpContext Context
        {
            get { return _context; }
        }

        #region Nested type: WorkerRequest

        private class WorkerRequest : SimpleWorkerRequest
        {
            private readonly bool _isSecure;

            public WorkerRequest(string page, string query, TextWriter output, bool isSecure)
                : base(page, query, output)
            {
                _isSecure = isSecure;
            }

            public override bool IsSecure()
            {
                return _isSecure;
            }
        }

        #endregion
    }
}